

package com.ly.blog_user.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ly.blog_common.constant.Constant;
import com.ly.blog_common.entity.SysUserEntity;
import com.ly.blog_common.entity.mq.EmailMqInfo;
import com.ly.blog_common.entity.mq.MqMsgEntity;
import com.ly.blog_common.response.BlogResponseStatus;
import com.ly.blog_common.security.JwtAuthenticationToken;
import com.ly.blog_common.utils.IPUtils;
import com.ly.blog_common.utils.R;
import com.ly.blog_common.utils.StringUtils;
import com.ly.blog_user.annotation.SysLog;
import com.ly.blog_user.base.AbstractController;
import com.ly.blog_user.feign.ThirdService;
import com.ly.blog_user.form.EmailForm;
import com.ly.blog_user.form.SysLoginForm;
import com.ly.blog_user.form.SysRegisterForm;
import com.ly.blog_user.security.SecurityUtils;
import com.ly.blog_user.service.SysCaptchaService;
import com.ly.blog_user.service.SysUserService;
import com.ly.blog_user.service.SysUserTokenService;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 登录相关
 */
@RestController
public class SysLoginController extends AbstractController {

	@Autowired
	private SysUserService sysUserService;

	@Autowired
	private SysUserTokenService sysUserTokenService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private SysCaptchaService sysCaptchaService;

	@Autowired
    private AuthenticationManager authenticationManager;

	@Autowired
    private ThirdService thirdService;

	/**
	 * 验证码
	 */
	@GetMapping("captcha.jpg")
	public void captcha(HttpServletResponse response, String uuid)throws IOException {
		response.setHeader("Cache-Control", "no-store, no-cache");
		response.setContentType("image/jpeg");

		//获取图片验证码
		BufferedImage image = sysCaptchaService.getCaptcha(uuid);

		ServletOutputStream out = response.getOutputStream();
		ImageIO.write(image, "jpg", out);
		IOUtils.closeQuietly(out);
	}

	/**
	 * 登录
     * 支持登录名或者邮箱地址
	 */
    @SysLog("用户名登录")
	@PostMapping("/sys/login")
	public R login(@RequestBody SysLoginForm form, HttpServletRequest request)throws IOException {
		boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());
		if(!captcha){
            return R.error(BlogResponseStatus.USER_LOGIN_CAPTCHA_ERROR);
		}

        // 系统登录认证
        JwtAuthenticationToken token = SecurityUtils.login(request, form.getUsername(), form.getPassword(), authenticationManager,redisTemplate,sysUserTokenService);

		return R.ok().put("token",token.getToken());
	}

	/**
	 * 登录
     * 支持登录名或者邮箱地址
	 */
    @SysLog("邮箱登录")
	@PostMapping("/sys/login/email")
	public R loginEmail(@RequestBody SysLoginForm form, HttpServletRequest request)throws IOException {
		boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());
		if(!captcha){
            return R.error(BlogResponseStatus.USER_LOGIN_CAPTCHA_ERROR);
		}

        boolean emailCode = sysCaptchaService.validate(form.getEmailUuid(), form.getPassword());
        if(!emailCode){
            return R.error(BlogResponseStatus.EMAIL_CODE_ERROR);
        }

        // 系统登录认证
        form.setPassword(Constant.LOGIN_EMAIL);
        JwtAuthenticationToken token = SecurityUtils.login(request, form.getUsername(), form.getPassword(), authenticationManager,redisTemplate,sysUserTokenService);

		return R.ok().put("token",token.getToken());
	}

	/**
	 * 注册
	 */
    @SysLog("注册用户")
	@PostMapping("/sys/register")
	public R register(@RequestBody SysRegisterForm form){
//		boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());
//		if(!captcha){
//			return R.error(BlogResponseStatus.USER_LOGIN_CAPTCHA_ERROR);
//		}

        boolean emailCode = sysCaptchaService.validate(form.getEmailUuid(), form.getEmailCode());
        if(!emailCode){
            return R.error(BlogResponseStatus.EMAIL_CODE_ERROR);
        }

        //检测账号是否存在
        String userName = form.getUsername();
        int count = sysUserService.count(new QueryWrapper<SysUserEntity>().eq("username", userName));
        if(count > 0){
            return R.error(BlogResponseStatus.USER_REGISTER_USERNAME_EXIST);
        }

        //开始注册
        SysUserEntity sysUserEntity = new SysUserEntity();
        sysUserEntity.setUsername(form.getUsername());
        sysUserEntity.setPassword(form.getPassword());
        sysUserEntity.setEmail(form.getEmail());
        sysUserEntity.setAlias(StringUtils.isBlank(form.getAlias())?form.getUsername():form.getAlias());
        //状态 1、ok 0、锁定
        sysUserEntity.setStatus(1);

        //设定初始角色
        List<Long> roles= new ArrayList<>();
        roles.add(1L);
        sysUserEntity.setRoleIdList(roles);

		sysUserService.saveUser(sysUserEntity);
		return R.ok();
	}

    /**
     * 检测用户名是否存在
     * @param username
     * @return
     */
    @GetMapping("/sys/check/username/{username}")
	public R checkUsernameUsed(@PathVariable("username") String username){
        int countUserName = sysUserService.checkUsernameUsed(username);
        return countUserName == 0 ?R.ok():R.error(BlogResponseStatus.USERNAME_USED);
	}


    /**
     * 发送邮件
     */
    @PostMapping("/sys/send")
    public R send(@RequestBody EmailForm emailForm,HttpServletRequest request){
        //邮箱不能为空
        String email = emailForm.getEmail();
        if(StringUtils.isBlank(email)){
            return R.error(BlogResponseStatus.EMAIL_NO_EMPTY);
        }


        MqMsgEntity<EmailMqInfo> mqMsgEntity = new MqMsgEntity<>();
        EmailMqInfo emailMqInfo = new EmailMqInfo();
        //检测邮箱是否已被注册
        int count = sysUserService.checkEmailUsed(email);
        if(0 == emailForm.getType()) {
            if (count > 0) {
                return R.error(BlogResponseStatus.EMAIL_USED_ERROR);
            }
            mqMsgEntity.setType(MqMsgEntity.Type.EMAIL);
            emailMqInfo.setType(EmailMqInfo.Type.REGISTER.getTypeNumber());
        }else{
            if (count == 0) {
                return R.error(BlogResponseStatus.EMAIL_NO_REGISTER_ERROR);
            }
            mqMsgEntity.setType(MqMsgEntity.Type.EMAIL);
            emailMqInfo.setType(EmailMqInfo.Type.LOGIN.getTypeNumber());
        }


        String emailCode = sysCaptchaService.getEmailCode(emailForm.getUuid());
        Map<String,String> param = new HashMap<>();
        param.put("emailCode",emailCode);
        param.put("email",email);
        emailMqInfo.setEmail(email);
        emailMqInfo.setParam(param);
        mqMsgEntity.setMsg(emailMqInfo);

        //发送前进行标记：检测时间需要等待一分钟再发送 , 根据用户IP确定单次发送时间 , 超时时间 1分钟
        String ipAddr = IPUtils.getIpAddr(request);
        String key = "EMAIL_SEND_RECORD:" + ipAddr.replace(":","_"); //通过 : 分隔 redis文件夹
        Boolean isExist = redisTemplate.opsForValue().setIfAbsent(key, emailForm,60,TimeUnit.SECONDS);
        if(!isExist){
            return R.error(BlogResponseStatus.EMAIL_SEND_DELAY);
        }

        R r = thirdService.send(mqMsgEntity);
        return r.getCode() == 0 ?R.ok():R.error(BlogResponseStatus.EMAIL_SEND_ERROR);
    }

	/**
	 * 退出
	 */
    @SysLog("登出用户")
	@GetMapping("/sys/logout")
	public R logout(HttpServletRequest request) {
		sysUserTokenService.logout(getUserId(),request);
		return R.ok();
	}
	
}
